package com.cheer.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.dao.*;
import com.cheer.dto.StandingBookReviewLogDTO;
import com.cheer.dto.StandingBookReviewPageDTO;
import com.cheer.entity.*;
import com.cheer.enums.*;
import com.cheer.exception.ServiceException;
import com.cheer.manager.StandingBookReviewManager;
import com.cheer.service.StandingBookReviewService;
import com.cheer.vo.Page;
import com.cheer.vo.StandingBookReviewLogVO;
import com.cheer.vo.StandingBookReviewVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author cheer
 */
@Service
public class StandingBookReviewServiceImpl extends ServiceImpl<StandingBookReviewDao, StandingBookReview>
        implements StandingBookReviewService {

    @Autowired
    private StandingBookDao standingBookDao;

    @Autowired
    private OrganizationDao organizationDao;

    @Autowired
    private ApplicantDao applicantDao;

    @Autowired
    private StandingBookReviewDao standingBookReviewDao;

    @Autowired
    private StandingBookReviewLogDao standingBookReviewLogDao;

    @Autowired
    private AdminDao adminDao;

    @Autowired
    private StandingBookReviewManager standingBookReviewManager;

    @Override
    public Page<StandingBookReviewVO> getPage(Integer pageNum, Integer pageSize, Long reviewOrgId, Long orgId, String applicantName,
                                              String contactPerson, Integer status, Date startTime, Date endTime) {
        // 参数处理
        String orgPath = null;
        if (orgId != null) {
            Organization organization = organizationDao.selectById(orgId);
            if (organization == null) {
                return null;
            } else {
                orgPath = organization.getOrgPath();
            }
        }
        applicantName = StringUtils.trimToNull(applicantName);
        contactPerson = StringUtils.trimToNull(contactPerson);
        // 分页查询
        PageHelper.startPage(pageNum, pageSize);
        List<StandingBookReviewPageDTO> reviewDTOS = standingBookReviewDao.listPage(reviewOrgId, orgPath, applicantName,
                contactPerson, status, startTime, endTime);
        PageInfo<StandingBookReviewPageDTO> pageInfo = new PageInfo<>(reviewDTOS);
        // 返回数据处理
        List<StandingBookReviewVO> reviewVOS = reviewDTOS.stream().map(StandingBookReviewPageDTO::build).collect(Collectors.toList());
        return new Page<StandingBookReviewVO>().setPageNum(pageInfo.getPageNum())
                .setPageSize(pageInfo.getPageSize())
                .setPages(pageInfo.getPages())
                .setTotal(pageInfo.getTotal())
                .setContent(reviewVOS);
    }

    @Override
    @Transactional
    public void approveReview(Long accountId, Long reviewId) {
        // 验证数据
        StandingBookReview review = checkReview(reviewId);
        Organization organization = organizationDao.selectById(review.getReviewOrgId());
        if (organization == null) {
            throw new ServiceException("审核的组织机构已失效");
        }
        Applicant applicant = applicantDao.getByAccountId(review.getAccountId());
        if (applicant == null) {
            throw new ServiceException("审核的集体已失效");
        }
        StandingBook standingBook = standingBookDao.getByAccountId(review.getAccountId());
        if (standingBook == null) {
            throw new ServiceException("审核的台账已失效");
        }
        Admin admin = adminDao.getByAccountId(accountId);
        if (admin == null) {
            throw new ServiceException("您的账号已失效");
        }
        // 更新审核状态
        standingBookReviewManager.updateReview(review, ReviewStatusEnum.PASSED, admin.getId());
        // 如果当前审核为该审核流的最后一层，就授予集体荣誉，否则提交到上级
        if (isFinish(applicant, organization)) {
            awardTitle(applicant, standingBook);
        } else {
            submitToParentOrg(applicant, organization);
        }
    }

    @Override
    @Transactional
    public void denyReview(Long accountId, Long reviewId) {
        // 验证数据
        StandingBookReview review = checkReview(reviewId);
        StandingBook standingBook = standingBookDao.getByAccountId(review.getAccountId());
        if (standingBook == null) {
            throw new ServiceException("审核的台账已失效");
        }
        Admin admin = adminDao.getByAccountId(accountId);
        if (admin == null) {
            throw new ServiceException("您的账号已失效");
        }
        // 更新审核状态
        standingBookReviewManager.updateReview(review, ReviewStatusEnum.NOT_PASSED, admin.getId());
        // 返回给上一级，如果当前为第一级，返回给用户
        if (review.getPrevOrgId() != 0) {
            StandingBookReview updateReview = new StandingBookReview();
            updateReview.setReviewStatus(ReviewStatusEnum.UP_NOT_PASSED.getCode());
            standingBookReviewDao.updateByAccountIdAndReviewOrgId(updateReview, review.getAccountId(), review.getPrevOrgId());
        } else {
            StandingBook updateStandingBook = new StandingBook();
            updateStandingBook.setId(standingBook.getId());
            updateStandingBook.setReviewStatus(ReviewedStatusEnum.NOT_PASSED.getCode());
            standingBookDao.updateById(updateStandingBook);
        }
    }

    @Override
    @Transactional
    public void rejectReview(Long accountId, Long reviewId) {
        // 验证数据
        StandingBookReview review = checkReview(reviewId);
        StandingBook standingBook = standingBookDao.getByAccountId(review.getAccountId());
        if (standingBook == null) {
            throw new ServiceException("审核的台账已失效");
        }
        Admin admin = adminDao.getByAccountId(accountId);
        if (admin == null) {
            throw new ServiceException("您的账号已失效");
        }
        // 更新审核状态
        standingBookReviewManager.updateReview(review, ReviewStatusEnum.REJECTED, admin.getId());
        // 前面所有审核过的都变为驳回
        List<Long> prevReviewIds = new ArrayList<>();
        long prevOrgId = review.getPrevOrgId();
        while (prevOrgId != 0) {
            StandingBookReview prevReview = standingBookReviewDao.getByAccountIdAndOrgId(review.getAccountId(), prevOrgId);
            if (prevReview == null) {
                break;
            }
            prevReviewIds.add(prevReview.getId());
            prevOrgId = prevReview.getPrevOrgId();
        }
        if (CollectionUtils.isNotEmpty(prevReviewIds)) {
            StandingBookReview rejectedReview = new StandingBookReview();
            rejectedReview.setReviewStatus(ReviewStatusEnum.REJECTED.getCode());
            standingBookReviewDao.updateByIds(rejectedReview, prevReviewIds);
        }
        // 更新台账状态
        StandingBook updateStandingBook = new StandingBook();
        updateStandingBook.setId(standingBook.getId());
        updateStandingBook.setReviewStatus(ReviewedStatusEnum.REJECTED.getCode());
        standingBookDao.updateById(updateStandingBook);
    }

    private StandingBookReview checkReview(Long reviewId) {
        StandingBookReview review = standingBookReviewDao.selectById(reviewId);
        if (review == null) {
            throw new ServiceException("审核已失效");
        }
        if (review.getReviewStatus() == ReviewStatusEnum.PASSED.getCode() ||
                review.getReviewStatus() == ReviewStatusEnum.NOT_PASSED.getCode() ||
                review.getReviewStatus() == ReviewStatusEnum.REJECTED.getCode()) {
            throw new ServiceException("您当前无权限对该审核流程进行审批");
        }
        return review;
    }

    /**
     * 审核是否完成
     *
     * @param applicant    集体信息
     * @param organization 机构信息
     */
    private Boolean isFinish(Applicant applicant, Organization organization) {
        // 市级称号到市地团委就结束
        if (applicant.getRegisterTitle() <= TitleEnum.CITY.getType() &&
                organization.getOrgRole() == RoleEnum.SECOND_ADMIN.getCode()) {
            return true;
        }
        // 省级称号到团省委就结束
        if (applicant.getRegisterTitle() >= TitleEnum.PROVINCE.getType() &&
                organization.getOrgRole() == RoleEnum.SUPER_ADMIN.getCode()) {
            return true;
        }
        return false;
    }

    /**
     * 审核通过，授予荣誉
     *
     * @param applicant    集体信息
     * @param standingBook 台账信息
     */
    private void awardTitle(Applicant applicant, StandingBook standingBook) {
        // 更新台账状态
        StandingBook updateStandingBook = new StandingBook();
        updateStandingBook.setId(standingBook.getId());
        updateStandingBook.setReviewStatus(ReviewedStatusEnum.PASSED.getCode());
        standingBookDao.updateById(updateStandingBook);
        // 更新集体荣誉称号
        Applicant updateApplicant = new Applicant();
        updateApplicant.setId(applicant.getId());
        if (applicant.getRegisterTitle() == TitleEnum.NO.getType()) {
            updateApplicant.setTitle(TitleEnum.CITY.getType());
            updateApplicant.setTitleYear(String.valueOf(DateUtil.year(new Date())));
        } else {
            updateApplicant.setTitle(applicant.getRegisterTitle());
        }
        applicantDao.updateById(updateApplicant);
    }

    /**
     * 提交审核到上级
     *
     * @param applicant    集体信息
     * @param organization 机构信息
     */
    private void submitToParentOrg(Applicant applicant, Organization organization) {
        long parentOrgId = organization.getParentOrgId();
        Organization parentOrg = null;
        while (parentOrgId != 0) {
            parentOrg = organizationDao.selectById(parentOrgId);
            if (parentOrg == null) {
                throw new ServiceException("您的上级组织机构已失效，无法继续审核");
            }
            if (!parentOrg.getCategory()) {
                break;
            }
            parentOrgId = parentOrg.getParentOrgId();
        }
        if (parentOrg != null) {
            standingBookReviewManager.submitReview(applicant.getAccountId(), parentOrg.getId(), organization.getId());
        }
    }

    @Override
    public List<StandingBookReviewLogVO> getLog(Long reviewId) {
        StandingBookReview review = standingBookReviewDao.selectById(reviewId);
        if (review == null) {
            return null;
        }
        List<StandingBookReviewLogDTO> logs = standingBookReviewLogDao.listByAccountId(review.getAccountId(),
                SubmitTypeEnum.NEW.getCode());
        return logs.stream()
                .map(StandingBookReviewLogDTO::build)
                .collect(Collectors.toList());
    }
}
